package cn.kent;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.function.Consumer;

/**
 * Lambda 表达式的使用
 *  格式：
 *      Lambda表达式左边：lambda形参列表（）其实就是接口中的抽象方法的形参列表
 *      Lambda表达式右边：lambda体 （其实就是重写的抽象方法的方法体）
 * 使用（分为6种情况）：
 *      总结：
 *          左边:形参列表的参数类型可以省略(类型推断)，如果lambda形参列表只有一个参数，那么 ()小括号 可以省略
 *          右边:使用{}包裹，如果只有一条执行语句，或者return，那么return和{}都可以省略，多条则不能省略{}
 * lambda表达式的实质: 作为接口的实例 【必须是函数式接口】
 *
 * 如果一个接口中，只声明了一个抽象方法，则此接口就称为函数式接口。
 */
public class LambdaTest02 {

    @Test
    public void test1() {
        // 第一种情况，无参无返回值 -- Runnable
        final Runnable r1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("线程执行");
            }
        };
        r1.run();

        Runnable r2 = ()->{
            System.out.println("线程执行lambda");
        };
        r2.run();
    }

    @Test
    public void test2() {
        // 第二种情况，需要一个参数，但是没有返回值
        final Consumer<String> con = new Consumer<String>() {
            public void accept(String s) {
                System.out.println(s);
            }
        };
        con.accept("谎言和誓言的区别是什么？");

        System.out.println("lambda表达式改进后：");

        Consumer<String> c = (String s) -> {
            System.out.println(s);
        };

        c.accept("一个听的人当真了，一个说的人当真了");
    }

    @Test
    public void test3() {
        // 第三种情况：数据类型可以忽略，因为可由编译器推断得出，成为“类型推断”
        final Consumer<String> con = new Consumer<String>() {
            public void accept(String s) {
                System.out.println(s);
            }
        };
        con.accept("谎言和誓言的区别是什么？");

        System.out.println("lambda表达式改进后：");

        Consumer<String> c = (s) -> {
            System.out.println(s);
        };

        c.accept("一个听的人当真了，一个说的人当真了");

        // 类型推断演示
        final ArrayList<String> list = new ArrayList<>(); // 类型推断 ArrayList<>不需要指定String
        int[] nums = new int[]{1, 2, 3};
        int[] nums2 = {1, 2, 3}; // 类型推断 不需要指定new int[] 而是直接{数据}
    }

    @Test
    public void test4() {
        // 第四种情况，lambda若只需要一个参数时，参数的小括号可以省略
        Consumer<String> consumer = s -> {
            System.out.println(s);
        };
        consumer.accept("一个是听得人当真了，一个是说的人当真了");
    }

    @Test
    public void test5() {
        // lambda 表达式 需要两个以上的参数，多条执行语句，并且可以有返回值
        Comparator<Integer> com = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                System.out.println("o1 = " + o1);
                System.out.println("o2 = " + o2);
                return Integer.compare(o1, o2);
            }
        };
        System.out.println(com.compare(12, 21));

        System.out.println("======================");

        Comparator<Integer> com2 = (o1, o2) -> {
            System.out.println("o1 = " + o1);
            System.out.println("o2 = " + o2);
            return Integer.compare(o1, o2);
        };
        System.out.println(com2.compare(12, 21));
    }


    @Test
    public void test6() {
        // 第六种情况，当lambda只有一条时，return若与大括号都有，那么都可以省略
        Comparator<Integer> com = (o1, o2) -> {
            return Integer.compare(o1, o2);
        };
        System.out.println(com.compare(12, 21));

        Comparator<Integer> com2 = (o1, o2) ->
                Integer.compare(o1, o2);

        System.out.println(com2.compare(12, 21));

        Consumer<String> consumer = s ->
                System.out.println(s);
        consumer.accept("一个是说的人当真了，一个是听得人当真了");
    }


}
